package one.stand.eureka.info;

import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;

import java.util.concurrent.TimeUnit;

@Slf4j
public class DefaultServiceInfo implements IServiceInfo {

    private static LogWriter logWriter = new LogWriter();
    private CommandExecuter commandExecuter = new CommandExecuter();
    private ApplicationInfoManagerHandler applicationInfoManagerHandler;
    private ServiceConfigReader serviceConfigReader;

    public DefaultServiceInfo(ApplicationInfoManagerHandler applicationInfoManagerHandler, ServiceConfigReader serviceConfigReader) {
        this.applicationInfoManagerHandler = applicationInfoManagerHandler;
        this.serviceConfigReader = serviceConfigReader;
    }

    @Override
    @Async
    public void deploy(String name, String commandKey) {
        String key = name + ":" + commandKey;
        log.warn("command(key={}) deploy", key);
        logWriter.init(key, "deploy(key={" + key + "}) start...");

        String command = serviceConfigReader.getCommand(name, commandKey);
        boolean flag = commandExecuter.exe(command, key);
        if (!flag) {
            return;
        }

        // check project status
        boolean isUp = checkUp(name, key);
        if (isUp) {
            logWriter.success(key, "deploy is end!!!");
        } else {
            logWriter.error(key, "Project restart fail");
        }
    }

    @Override
    public String logs(String name, String commandKey) {
        String key = name + ":" + commandKey;
        return logWriter.poll(key);
    }

    private boolean checkUp(String name, String key) {
        if (serviceConfigReader.checkTure(name)) return true;

        boolean isUp = false;
        Stopwatch watch = Stopwatch.createStarted();
        try {
            while (watch.elapsed(TimeUnit.SECONDS) < 30) {
                isUp = applicationInfoManagerHandler.isUp(name);
                logWriter.info(key, "Project status:" + isUp);
                if (isUp && watch.elapsed(TimeUnit.SECONDS) > 3) {
                    break;
                }
                Thread.sleep(500);
            }
            watch.stop();
        } catch (InterruptedException e) {
            watch.stop();
            log.error(e.getMessage(), e);
            logWriter.error(key, "exception found");
        }
        return isUp;
    }
}
